﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.IO;
using System.Threading;
using ajayumi.develop.win32.Transport.Utils;
using ajayumi.develop.win32.Transport.WCF.Services.Interfaces;
using ajayumi.develop.win32.Transport.WCF.Services;

namespace ajayumi.develop.win32.Transport.WCF.ServiceImpls
{
    /// <summary>
    /// 文件传输实现类
    /// Author  : 黄乙冬
    /// Date    : 2011-08-28
    /// </summary>
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
     InstanceContextMode = InstanceContextMode.Single,
     UseSynchronizationContext = false)]
    public class TransportFileService : TransportFileBase, ITransportFile
    {
        public Services.DataContracts.TransFileInfo InitUploadFile(Services.DataContracts.TransFileInfo file)
        {
            string ip = this.GetClientIp();
            file.IP = ip;

            //通过委托方法得到文件的保存目录
            string saveDir = this.GetSaveDirectory();
            file.SavePath = Path.Combine(saveDir, file.RelativePath);
            //创建文件目录
            FileHelper.CreateDir(file.SavePath);

            int progressPercentage = 0;
            lock (this.m_LockObj)
            {
                FileInfo fileInfo = new FileInfo(file.SavePath);
                if (fileInfo.Exists)
                {
                    file.CreationTime = fileInfo.CreationTime;
                    file.LastAccessTime = fileInfo.LastAccessTime;
                    file.Offset = fileInfo.Length;
                    progressPercentage = Convert.ToInt32(Convert.ToSingle(fileInfo.Length) / Convert.ToSingle(file.Length) * 100f);
                }
                fileInfo = null;
            }

            this.OnTransReady(new TransReadyEventArgs(file.TransportAction, ip, file.RelativePath, file.Length, progressPercentage));

            if (file.Offset == file.Length)
            {
                this.OnTransCompleted(new TransCompletedEventArgs(file.TransportAction,
                    file.RelativePath, file.SavePath, DateTime.Now,
                    null, false, this));
            }

            return file;
        }

        public Services.DataContracts.TransFileInfo UploadFile(Services.DataContracts.TransFileInfo file)
        {
            //using (FileStream fileStream = File.Open(file.SavePath, FileMode.OpenOrCreate))
            //{
            //    if (fileStream.Length == file.Length)
            //    {
            //        this.OnTransCompleted(new TransCompletedEventArgs(Services.TransportAction.Upload,
            //            file.RelativePath, file.SavePath, DateTime.Now,
            //            null, false, this));
            //    }
            //    else if (fileStream.Length > file.Length)
            //    {
            //        File.Delete(file.SavePath);
            //    }
            //    else
            //    {
            //        using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
            //        {
            //            long offset = file.Offset;
            //            binaryWriter.Seek((int)offset, SeekOrigin.Begin);
            //            binaryWriter.Write(file.Data);

            //            file.Offset = fileStream.Length;
            //        }

            //        int progressPercentage = Convert.ToInt32(Convert.ToSingle(file.Offset) / Convert.ToSingle(file.Length) * 100f);
            //        this.OnTransProgressChanged(new TransProgressChangedEventArgs(Services.TransportAction.Upload, file.RelativePath, progressPercentage, this));
            //        Console.WriteLine("{0} 服务器端接收数据: {1}字节 {2}%", DateTime.Now, file.Offset, progressPercentage);

            //        if (file.Offset == file.Length)
            //        {
            //            this.OnTransCompleted(new TransCompletedEventArgs(Services.TransportAction.Upload,
            //                file.RelativePath, file.SavePath, DateTime.Now,
            //                null, false, this));
            //        }
            //    }
            //}

            FileStream fileStream = null;
            BinaryWriter binaryWriter = null;
            int progressPercentage = 0;
            try
            {
                fileStream = File.Open(file.SavePath, FileMode.OpenOrCreate);

                if (fileStream.Length == file.Length)
                {
                    this.OnTransCompleted(new TransCompletedEventArgs(file.TransportAction,
                        file.RelativePath, file.SavePath, DateTime.Now,
                        null, false, this));
                }
                else if (fileStream.Length > file.Length)
                {
                    File.Delete(file.SavePath);
                }
                else
                {
                    binaryWriter = new BinaryWriter(fileStream);

                    long offset = file.Offset;
                    binaryWriter.Seek((int)offset, SeekOrigin.Begin);
                    binaryWriter.Write(file.Data);

                    file.Offset = fileStream.Length;

                    progressPercentage = Convert.ToInt32(Convert.ToSingle(file.Offset) / Convert.ToSingle(file.Length) * 100f);
                    this.OnTransProgressChanged(new TransProgressChangedEventArgs(file.TransportAction, file.RelativePath, progressPercentage, this));
                    Console.WriteLine("{0} 服务器端接收数据: {1}字节 {2}%", DateTime.Now, file.Offset, progressPercentage);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("{0} 服务器端接收数据: {1}字节 {2}% 时发生错误，错误信息：\n{3}", DateTime.Now, file.Offset, progressPercentage, ex.Message);
            }
            finally
            {
                if (binaryWriter != null) binaryWriter.Close();
                if (fileStream != null) fileStream.Close();

                if (file.Offset == file.Length)
                {
                    this.OnTransCompleted(new TransCompletedEventArgs(file.TransportAction,
                        file.RelativePath, file.SavePath, DateTime.Now,
                        null, false, this));
                }
            }

            file.Data = null;
            return file;
        }

        public Services.DataContracts.TransFileInfo InitDownloadFile(Services.DataContracts.TransFileInfo file)
        {
            FileInfo fileInfo = new FileInfo(file.FullPath);
            if (fileInfo.Exists)
            {
                file.Length = fileInfo.Length;
                file.CreationTime = fileInfo.CreationTime;
                file.LastAccessTime = fileInfo.LastAccessTime;
                file.IP = this.GetClientIp();
                int progressPercentage = 0;
                if (file.Length > 0)
                {
                    progressPercentage = Convert.ToInt32(Convert.ToSingle(file.Offset) / Convert.ToSingle(fileInfo.Length) * 100f);
                }
                this.OnTransReady(new TransReadyEventArgs(file.TransportAction,
                   file.IP,
                   file.RelativePath,
                   file.Length,
                   progressPercentage));

                if (file.Length <= 0)
                {
                    this.OnTransCompleted(new TransCompletedEventArgs(file.TransportAction,
                        file.RelativePath, file.FullPath, DateTime.Now,
                        null, false, this));
                }
            }

            return file;
        }

        public Services.DataContracts.TransFileInfo DownloadFile(Services.DataContracts.TransFileInfo file)
        {
            if (File.Exists(file.FullPath))
            {
                long length = 0L;
                long fileLength = 0L;
                using (FileStream fileStream = File.OpenRead(file.FullPath))
                {
                    fileLength = fileStream.Length;
                    int bufferMaxSize = this.GetBufferSize.Invoke() * 1024;   //每次下传的数据块大小(Kb)
                    long bufferLength = file.Length - file.Offset >= bufferMaxSize ? bufferMaxSize : file.Length - file.Offset;
                    file.Data = new byte[bufferLength];
                    fileStream.Position = file.Offset;
                    fileStream.Read(file.Data, 0, file.Data.Length);

                    length = file.Offset + bufferLength;

                    int progressPercentage = Convert.ToInt32(Convert.ToSingle(length) / Convert.ToSingle(fileStream.Length) * 100f);
                    this.OnTransProgressChanged(new TransProgressChangedEventArgs(file.TransportAction, file.RelativePath, progressPercentage, this));
                    Console.WriteLine("{0} 服务器端发送数据: {1}字节 {2}%", DateTime.Now, length, progressPercentage);
                }

                if (length == fileLength)
                {
                    this.OnTransCompleted(new TransCompletedEventArgs(file.TransportAction,
                        file.RelativePath, file.FullPath, DateTime.Now,
                        null, false, this));
                }
            }

            return file;
        }
    }
}
